package com.dolphin.component;

import com.dolphin.commons.OptionCacheUtil;
import com.dolphin.model.Option;
import com.dolphin.service.OptionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 描述:
 * ${DESCRIPTION}
 *
 * @author 小海豚
 * @create 2022-10-25 23:48
 * 个人博客地址：https://www.nonelonely.com
 */
@Component
public class SensitiveWordComponent {
    @Autowired
    private OptionService optionService;

    public SensitiveWordComponent() {
    }

    public boolean contains(String txt, String matchType) {
        Map<String, String> wordMaps = this.getWordMaps();
        if (wordMaps != null && wordMaps.size() != 0) {
            boolean flag = false;

            for (int i = 0; i < txt.length(); ++i) {
                int matchFlag = this.checkSensitiveWord(txt, i, matchType);
                if (matchFlag > 0) {
                    flag = true;
                }
            }

            return flag;
        } else {
            return false;
        }
    }

    public boolean contains(String txt) {
        return this.contains(txt, this.getMatchType());
    }

    public Set<String> getSensitiveWord(String txt) {
        return this.getSensitiveWord(txt, this.getMatchType());
    }

    public String replaceSensitiveWord(String txt, char replaceChar, String matchType) {
        String resultTxt = txt;
        Set<String> set = this.getSensitiveWord(txt, matchType);

        String word;
        String replaceString;
        for (Iterator iterator = set.iterator(); iterator.hasNext(); resultTxt = resultTxt.replaceAll(word, replaceString)) {
            word = (String) iterator.next();
            replaceString = this.getReplaceChars(replaceChar, word.length());
        }

        return resultTxt;
    }

    public String replaceSensitiveWord(String txt, char replaceChar) {
        return this.replaceSensitiveWord(txt, replaceChar, this.getMatchType());
    }

    public String replaceSensitiveWord(String txt, String replaceStr) {
        return this.replaceSensitiveWord(txt, replaceStr, this.getMatchType());
    }

    private String getReplaceChars(char replaceChar, int length) {
        StringBuilder resultReplace = new StringBuilder(String.valueOf(replaceChar));

        for (int i = 1; i < length; ++i) {
            resultReplace.append(replaceChar);
        }

        return resultReplace.toString();
    }

    public String replaceSensitiveWord(String txt, String replaceStr, String matchType) {
        String resultTxt = txt;
        Set<String> set = this.getSensitiveWord(txt, matchType);

        String word;
        for (Iterator iterator = set.iterator(); iterator.hasNext(); resultTxt = resultTxt.replaceAll(word, replaceStr)) {
            word = (String) iterator.next();
        }

        return resultTxt;
    }

    public Set<String> getSensitiveWord(String txt, String matchType) {
        Set<String> sensitiveWordList = new HashSet();

        for (int i = 0; i < txt.length(); ++i) {
            int length = this.checkSensitiveWord(txt, i, matchType);
            if (length > 0) {
                sensitiveWordList.add(txt.substring(i, i + length));
                i = i + length - 1;
            }
        }

        return sensitiveWordList;
    }

    private int checkSensitiveWord(String txt, int beginIndex, String matchType) {
        boolean flag = false;
        int matchFlag = 0;
        Map nowMap = this.getWordMaps();

        for (int i = beginIndex; i < txt.length(); ++i) {
            char word = txt.charAt(i);
            nowMap = (Map) nowMap.get(word);
            if (nowMap == null) {
                break;
            }

            ++matchFlag;
            if ("1".equals(nowMap.get("isEnd"))) {
                flag = true;
                if ("MIN".equalsIgnoreCase(matchType)) {
                    break;
                }
            }
        }

        if (matchFlag < 2 || !flag) {
            matchFlag = 0;
        }

        return matchFlag;
    }

    private Map<String, String> getWordMaps() {
        Map<String, String> wordMaps = null;
        String wordMapDb = OptionCacheUtil.getValue("COMMENT_SENSITIVE_WORD_DB");
        wordMapDb = StringUtils.trimToEmpty(wordMapDb);
        if (StringUtils.isEmpty(wordMapDb)) {
            Option option = this.optionService.getOptionByKey("COMMENT_SENSITIVE_WORD_DB");
            if (option != null) {
                wordMapDb = option.getOptionValue();
            }
        }

        wordMapDb = StringUtils.trimToEmpty(wordMapDb);
        if (StringUtils.isNotEmpty(wordMapDb)) {
            String[] sensitiveWords = wordMapDb.split(",");
            wordMaps = new HashMap(sensitiveWords.length);
            Iterator iterator = Arrays.stream(sensitiveWords).iterator();

            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                Map nowMap = wordMaps;

                for (int i = 0; i < key.length(); ++i) {
                    char keyChar = key.charAt(i);
                    Object wordMap = ((Map) nowMap).get(keyChar);
                    if (wordMap != null) {
                        nowMap = (Map) wordMap;
                    } else {
                        Map<String, String> newWorMap = new HashMap();
                        newWorMap.put("isEnd", "0");
                        ((Map) nowMap).put(keyChar, newWorMap);
                        nowMap = newWorMap;
                    }

                    if (i == key.length() - 1) {
                        ((Map) nowMap).put("isEnd", "1");
                    }
                }
            }
        }

        return wordMaps;
    }

    private String getMatchType() {
        Option option = this.optionService.getOptionByKey("COMMENT_SENSITIVE_MATCH_TYPE");
        return option != null && StringUtils.isNotEmpty(option.getOptionValue()) ? option.getOptionValue() : "MAX";
    }
}
